package com.sdhs.analyze.service.monitor;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sdhs.analyze.bean.DicNodeType;
import com.sdhs.analyze.bean.InfoNodeStatus;
import com.sdhs.analyze.bean.monitorinfo.*;
import com.sdhs.analyze.bean.org.OrgInfo;
import com.sdhs.analyze.common.BizConstants;
import com.sdhs.analyze.utils.RedisUtil;
import com.sdhs.analyze.utils.StatusCheckUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class IndexService {

    @Autowired
    private NodeStatusService nodeStatusService;

    @Autowired
    private RedisUtil redisUtil;

    private String split = "|";

    /**
     * 检测门架系统各类运行指标
     * @param orgInfo
     * @param nodeStatusMap
     * @param nodeTypeMap
     * @param parentNodeStatus
     * @return
     */
    public InfoNodeStatus indexMonitor(
            OrgInfo orgInfo,
            Map<String,InfoNodeStatus> nodeStatusMap,
            Map<String, DicNodeType> nodeTypeMap,
            InfoNodeStatus parentNodeStatus,
            GantryMonitorInfo gantryMonitorInfo) {

        DicNodeType indexNodeType = nodeTypeMap.get(BizConstants.NODE_TYPE_INDEX);

        InfoNodeStatus indexNodeStatus = nodeStatusService.makeNodeStatus(
                indexNodeType,
                orgInfo.getOrgId(),
                orgInfo.getOrgName() + "|" + indexNodeType.getNodeTypeName(),
                orgInfo.getOrgId(),
                BizConstants.NODE_STATUS_UNKNOWN,
                orgInfo.getOrgId(),
                "",
                new Date(0)
        );

        Date now = new Date();

        /* 新状态 */
        List<InfoNodeStatus> newNodeStatus = new ArrayList<>();

        /* 获取近24小时rsu交易成功率 */
        RsuHourSuccessRate rsuSuccessRate = getRsuSuccessRate24Hours(orgInfo, now);

        /* 获取近24小时牌识匹配成功率 */
        CameraSuccessRate cameraSuccessRate = getCameraSuccessRate24Hours(orgInfo, now);

        /* ETC交易成功率 只检测第一排门架 */
        /* 总交易数过低的，不视为异常 */
        InfoNodeStatus etcSuccessRateNodeStatus = StatusCheckUtils.checkStatusByThreshold(
                orgInfo.getOrderNum().equals("01") && rsuSuccessRate.getTotalEtcCnt() > 100 ?
                        (int)Math.floor(rsuSuccessRate.getEtcSuccessRate()/100.0) : 100,
                now,
                nodeTypeMap.get(BizConstants.NODE_TYPE_INDEX_ETC_SUCCESSRATE),
                orgInfo.getOrgId(),
                orgInfo.getOrgName() + split + nodeTypeMap.get(BizConstants.NODE_TYPE_INDEX_ETC_SUCCESSRATE).getNodeTypeName(),
                orgInfo.getOrgId(),
                indexNodeStatus);
        newNodeStatus.add(etcSuccessRateNodeStatus);

        gantryMonitorInfo.getEtcSuccessRate().setStatus(etcSuccessRateNodeStatus.getStatus());

        gantryMonitorInfo.getEtcSuccessRate().setRemark(String.format("%d|%d|%d",
                rsuSuccessRate.getEtcSuccessRate(),
                rsuSuccessRate.getEtcSuccessCnt(),
                rsuSuccessRate.getTotalEtcCnt()
                ));

        /* CPC交易成功率 只检测第一排门架 */
        /* 总交易数过低的，不视为异常 */
        InfoNodeStatus cpcSuccessRateNodeStatus = StatusCheckUtils.checkStatusByThreshold(
                orgInfo.getOrderNum().equals("01") && rsuSuccessRate.getTotalCpcCnt() > 100 ?
                        (int)Math.floor(rsuSuccessRate.getCpcSuccessRate()/100.0) : 100,
                now,
                nodeTypeMap.get(BizConstants.NODE_TYPE_INDEX_CPC_SUCCESSRATE),
                orgInfo.getOrgId(),
                orgInfo.getOrgName() + split + nodeTypeMap.get(BizConstants.NODE_TYPE_INDEX_CPC_SUCCESSRATE).getNodeTypeName(),
                orgInfo.getOrgId(),
                indexNodeStatus);
        newNodeStatus.add(cpcSuccessRateNodeStatus);

        gantryMonitorInfo.getCpcSuccessRate().setStatus(cpcSuccessRateNodeStatus.getStatus());

        gantryMonitorInfo.getCpcSuccessRate().setRemark(String.format("%d|%d|%d",
                rsuSuccessRate.getCpcSuccessRate(),
                rsuSuccessRate.getCpcSuccessCnt(),
                rsuSuccessRate.getTotalCpcCnt()
        ));

        /* 牌识匹配率 */
        /* 总数过低的，不视为异常 */
        InfoNodeStatus vehMatchSuccessRateNodeStatus = StatusCheckUtils.checkStatusByThreshold(
                cameraSuccessRate.getTotalCnt() > 100 ?
                        (int)Math.floor(cameraSuccessRate.getSuccessRate()/100.0) : 100,
                now,
                nodeTypeMap.get(BizConstants.NODE_TYPE_INDEX_VEHMATCH_SUCCESSRATE),
                orgInfo.getOrgId(),
                orgInfo.getOrgName() + split + nodeTypeMap.get(BizConstants.NODE_TYPE_INDEX_VEHMATCH_SUCCESSRATE).getNodeTypeName(),
                orgInfo.getOrgId(),
                indexNodeStatus);
        newNodeStatus.add(vehMatchSuccessRateNodeStatus);

        gantryMonitorInfo.getVehMatchSuccessRate().setStatus(vehMatchSuccessRateNodeStatus.getStatus());

        gantryMonitorInfo.getVehMatchSuccessRate().setRemark(String.format("%d|%d|%d",
                cameraSuccessRate.getSuccessRate(),
                cameraSuccessRate.getSuccessCnt(),
                cameraSuccessRate.getTotalCnt()
        ));


        for (InfoNodeStatus infoNodeStatus : newNodeStatus) {
            nodeStatusMap.put(infoNodeStatus.getKey(), infoNodeStatus);
        }

        nodeStatusMap.put(indexNodeStatus.getKey(), indexNodeStatus);

        /* 判断父节点的状态 */
        StatusCheckUtils.checkParentNodeStatus(indexNodeStatus.getStatus(),
                indexNodeStatus.getStatusCheckTime(),
                parentNodeStatus);

        return indexNodeStatus;
    }

    /**
     * 获得单门架的近24小时RSU交易成功率
     * @param orgInfo
     * @param now
     * @return
     */
    private RsuHourSuccessRate getRsuSuccessRate24Hours(OrgInfo orgInfo, Date now) {

        SimpleDateFormat sdfDay = new SimpleDateFormat("yyyyMMdd");
        SimpleDateFormat sdfHour = new SimpleDateFormat("HH");

        RsuHourSuccessRate successRate24Hours = new RsuHourSuccessRate();
        /* 获取最近24小时的总和 */
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(now);
        Long successCnt = 0l;
        Long failCnt = 0l;
        Long etcSuccessCnt = 0l;
        Long etcFailCnt = 0l;
        Long cpcSuccessCnt = 0l;
        Long cpcFailCnt = 0l;
        successRate24Hours.setOrgId(orgInfo.getOrgId());
        successRate24Hours.setOrgType(BizConstants.ORG_TYPE_GANTRY_FRONT);

        /* 组织查询key */
        List<String> keys = new ArrayList<>();
        for (int i = 0; i < 24; i++) {
            String day = sdfDay.format(calendar.getTime());
            String hour = sdfHour.format(calendar.getTime());
            String key = BizConstants.REDIS_KEY_PRE_GANTRY_RSU_HOUR_SUCCESS_RATE
                    + BizConstants.ORG_TYPE_GANTRY_FRONT + ":" + orgInfo.getOrgId() + ":" + day + ":" + hour;
            keys.add(key);
            calendar.add(Calendar.HOUR_OF_DAY, -1);
        }

        List<String> jsonStringList = redisUtil.multiGet(keys);

        /* 循环获取总成功数、失败数 */
        for (String jsonString : jsonStringList) {
            RsuHourSuccessRate successRate = null;
            if (jsonString != null) {
                successRate = JSON.parseObject(jsonString, RsuHourSuccessRate.class);
                successCnt += successRate.getSuccessCnt();
                failCnt += successRate.getFailCnt();
                etcSuccessCnt += successRate.getEtcSuccessCnt();
                etcFailCnt += successRate.getEtcFailCnt();
                cpcSuccessCnt += successRate.getCpcSuccessCnt();
                cpcFailCnt += successRate.getCpcFailCnt();
            }
        }
        successRate24Hours.setSuccessCnt(successCnt);
        successRate24Hours.setFailCnt(failCnt);
        successRate24Hours.setEtcSuccessCnt(etcSuccessCnt);
        successRate24Hours.setEtcFailCnt(etcFailCnt);
        successRate24Hours.setCpcSuccessCnt(cpcSuccessCnt);
        successRate24Hours.setCpcFailCnt(cpcFailCnt);

        Long totalCnt = successCnt + failCnt;
        Long etcTotalCnt = etcSuccessCnt + etcFailCnt;
        Long cpcTotalCnt = cpcSuccessCnt + cpcFailCnt;
        successRate24Hours.setTotalCnt(totalCnt);
        successRate24Hours.setTotalEtcCnt(etcTotalCnt);
        successRate24Hours.setTotalCpcCnt(cpcTotalCnt);
        int sucessRate = (totalCnt == 0) ? 0 :
                (int) Math.round(1.0 * successCnt / totalCnt * 10000.0);
        successRate24Hours.setSuccessRate(sucessRate);
        int etcSucessRate = (etcTotalCnt == 0) ? 0 :
                (int) Math.round(1.0 * etcSuccessCnt / etcTotalCnt * 10000.0);
        successRate24Hours.setEtcSuccessRate(etcSucessRate);
        int cpcSucessRate = (cpcTotalCnt == 0) ? 0 :
                (int) Math.round(1.0 * cpcSuccessCnt / cpcTotalCnt * 10000.0);
        successRate24Hours.setCpcSuccessRate(cpcSucessRate);

        /* 赋值门架名称 */
        successRate24Hours.setOrgName(orgInfo.getOrgName());

        /* 缓存，供查询使用 */
        String successRateKey = BizConstants.REDIS_KEY_PRE_GANTRY_RSU_HOUR_SUCCESS_RATE + BizConstants.ORG_TYPE_GANTRY_FRONT + ":" + orgInfo.getOrgId();

        redisUtil.set(successRateKey, JSONObject.toJSONString(successRate24Hours));

        return successRate24Hours;
    }

    /**
     * 获得单门架的近24小时牌识匹配率
     * @param now
     * @return
     */
    private CameraSuccessRate getCameraSuccessRate24Hours(OrgInfo orgInfo, Date now) {


        SimpleDateFormat sdfDay = new SimpleDateFormat("yyyyMMdd");
        SimpleDateFormat sdfHour = new SimpleDateFormat("HH");

        /* 从二级缓存获取 */
        String successRateKey =
                BizConstants.REDIS_KEY_PRE_GANTRY_CAMERA_HOUR_SUCCESS_RATE + BizConstants.ORG_TYPE_GANTRY_FRONT + ":" + orgInfo.getOrgId();
        String successRateString = redisUtil.get(successRateKey);
        CameraSuccessRate successRate24Hours = new CameraSuccessRate();

        if(successRateString == null) {
            /* 获取最近24小时的总和 */
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(now);
            Long successCnt = 0l;
            Long failCnt = 0l;
            successRate24Hours.setOrgId(orgInfo.getOrgId());
            successRate24Hours.setOrgType(BizConstants.ORG_TYPE_GANTRY_FRONT);

            /* 组织查询key */
            List<String> keys = new ArrayList<>();
            for (int i = 0; i < 24; i++) {
                String day = sdfDay.format(calendar.getTime());
                String hour = sdfHour.format(calendar.getTime());
                String key = BizConstants.REDIS_KEY_PRE_GANTRY_CAMERA_HOUR_SUCCESS_RATE
                        + BizConstants.ORG_TYPE_GANTRY_FRONT + ":" + orgInfo.getOrgId() + ":" + day + ":" + hour;
                keys.add(key);
                calendar.add(Calendar.HOUR_OF_DAY, -1);
            }

            List<String> jsonStringList = redisUtil.multiGet(keys);

            /* 循环获取总成功数、失败数 */
            for (String jsonString : jsonStringList) {
                RsuSuccessRate successRate = null;
                if (jsonString != null) {
                    successRate = JSON.parseObject(jsonString, RsuSuccessRate.class);
                    successCnt += successRate.getSuccessCnt();
                    failCnt += successRate.getFailCnt();
                }
            }
            successRate24Hours.setSuccessCnt(successCnt);
            successRate24Hours.setFailCnt(failCnt);
            Long totalCnt = successCnt + failCnt;
            int sucessRate = (totalCnt == 0) ? 0 :
                    (int) Math.round(1.0 * successCnt / totalCnt * 10000.0);
            successRate24Hours.setSuccessRate(sucessRate);
            successRate24Hours.setTotalCnt(totalCnt);

            /* 赋值门架名称 */
            successRate24Hours.setOrgName(orgInfo.getOrgName());

            redisUtil.set(successRateKey, JSONObject.toJSONString(successRate24Hours));
        }
        else {
            successRate24Hours = JSONObject.parseObject(successRateString, CameraSuccessRate.class);
        }

        return successRate24Hours;
    }
}
